import {_decorator, Component, find, Label, Node, Tween, tween, UITransform, Vec3, view} from "cc";
import {BloodTipDirectionEnum} from "db://assets/scripts/ui/common/BloodTipDirectionEnum";
import {PriorityEnum} from "db://assets/scripts/game/PriorityEnum";
import {GameManager} from "db://assets/scripts/game/GameManager";
import {FightTipEnum} from "db://assets/scripts/ui/common/FightTipEnum";
import {PoolManager} from "db://assets/scripts/common/PoolManager";
import {PlayerController} from "db://assets/scripts/game/role/player/PlayerController";
import {MonsterController} from "db://assets/scripts/game/role/monster/MonsterController";

const {ccclass, property} = _decorator;

/**
 * 战斗提示
 */
@ccclass('FightTipController')
export class FightTipController extends Component {
    /**
     * tween实例
     */
    private tipTween: Tween<Node>;
    /**
     * 缓动所需时间
     */
    private costTime: number = 1.5;
    /**
     * 三个不同方向
     */
    private directions: number[] = [BloodTipDirectionEnum.LEFT_UP, BloodTipDirectionEnum.LEFT_UP, BloodTipDirectionEnum.LEFT_UP];
    /**
     * 是否改变位置
     */
    private isChangePosition: boolean = false;
    /**
     * 目标位置
     */
    private targetPosition: Vec3 = new Vec3(0, 200, 0);
    /**
     * 初始位置
     */
    private originWorldPosition: Vec3 = new Vec3();
    /**
     * 当前位置
     */
    private currentWorldPosition: Vec3 = new Vec3();
    /**
     * 初始缩放
     */
    private originScale: Vec3 = new Vec3(0.7, 0.7, 0.7);
    /**
     * 初始角度
     */
    private originAngle: Vec3 = new Vec3();
    /**
     * 最开始缩放
     */
    private firstScale: Vec3 = new Vec3(1, 1, 1);
    /**
     * 最终缩放
     */
    private lastScale: Vec3 = new Vec3();

    start() {
        let strings: string[] = Object.keys(BloodTipDirectionEnum).map((key) => {
            return BloodTipDirectionEnum[key];
        });
    }

    update(deltaTime: number) {
        if (this.isChangePosition) {
            this.originWorldPosition.lerp(this.targetPosition, 0.05);
            GameManager.getInstance().mainCamera.convertToUINode(this.originWorldPosition, find('Canvas'), this.currentWorldPosition);
            this.node.setPosition(this.currentWorldPosition);
        }
    }

    /**
     * 展示血量提示
     *
     * @param scriptParent 使用者脚本
     * @param tipType 提示类型
     * @param blood 血量
     * @param callback 回调
     */
    public show(scriptParent: PlayerController | MonsterController,
                tipType: FightTipEnum,
                blood: number,
                callback?: Function) {
        // 停止缓动
        this.stopTipTween();
        this.node.eulerAngles = this.originAngle;
        this.node.setScale(this.originScale.x, this.originScale.y);

        this.isChangePosition = false;
        this.originWorldPosition.set(scriptParent.node.worldPosition);

        let childrens = this.node.children;
        childrens.forEach((item: Node) => {
            item.active = false;
        })

        this.node.setSiblingIndex(PriorityEnum.BLOOD_TIP);

        blood = Math.round(blood);
        let txt = String(blood);

        let childNode: Node;
        switch (tipType) {
            case FightTipEnum.ADD_BLOOD:
                childNode = this.node.getChildByName("addBlood") as Node;
                txt = "+" + txt;
                break;
            case FightTipEnum.REDUCE_BLOOD:
                childNode = this.node.getChildByName("reduceBlood") as Node;
                break;
            case FightTipEnum.CRITICAL_HIT:
                childNode = this.node.getChildByName("criticalHit") as Node;
                this.node.setSiblingIndex(PriorityEnum.BLOOD_CRITICAL_TIP);
                break;
        }

        let lbHitNum = childNode.getChildByName("num")?.getComponent(Label);
        lbHitNum && (lbHitNum.string = txt);

        childNode.active = true;

        let pos = this.node.getPosition();
        let width: number = childNode.getComponent(UITransform).width;
        let height: number = childNode.getComponent(UITransform).height;
        if ((Math.abs(pos.x) + width / 2) > view.getCanvasSize().width / 2) {
            let w = view.getCanvasSize().width / 2 - width / 2;
            pos.x = pos.x > 0 ? w : -w;
        }

        if ((Math.abs(pos.y) + height / 2) > view.getCanvasSize().height / 2) {
            let h = view.getCanvasSize().height / 2 - height / 2;
            pos.y = pos.y > 0 ? h : -h;
        }
        this.node.setPosition(pos);

        this.getTargetPos(scriptParent);

        this.isChangePosition = true;

        this.tipTween = tween(this.node)
            .to(this.costTime * 0.4, {scale: this.firstScale}, {easing: "smooth"})
            .to(this.costTime * 0.2, {scale: this.lastScale}, {easing: "backIn"})
            .call(() => {
                this.stopTipTween();
                PoolManager.getInstance().putNode(this.node);
                callback && callback();
                this.isChangePosition = false;
            })
            .start();
    }

    /**
     * 获取跟上次血量提示不一样方向的提示
     */
    private getTargetPos(scriptParent: PlayerController | MonsterController) {
        let dir: number;
        let arr = this.directions.concat();

        arr = arr.filter((item: any) => {
            return item !== scriptParent.bloodTipDirection;
        });

        dir = arr[Math.floor(Math.random() * arr.length)];
        switch (dir) {
            case BloodTipDirectionEnum.LEFT_UP:
                this.targetPosition.set(-2, 5, 0);
                break;
            case BloodTipDirectionEnum.MID_UP:
                this.targetPosition.set(0, 4, 0);
                break;
            case BloodTipDirectionEnum.RIGHT_UP:
                this.targetPosition.set(2, 2, 0);
                break;
            default:
                break;
        }

        this.targetPosition.add(scriptParent.node.worldPosition.clone());

        scriptParent.bloodTipDirection = dir;
    }

    /**
     * 停止缓动
     */
    private stopTipTween() {
        if (this.tipTween) {
            this.tipTween.stop();
            this.tipTween = null;
        }
    }
}

